Skip to main content

Credit - CS50x 2023

入门

打开 VS Code

首先点击你的终端窗口,然后单独执行 cd。 你会发现终端的“提示符”会显示如下。

然后在终端窗口执行

wget https://cdn.cs50.net/2022/fall/psets/1/credit.zip

然后按 Enter 键,以便在你的 codespace 中下载名为 credit.zip 的压缩包。 注意 wget 命令后URL前的空格,以及其他任何字符都不能省略!

你现在可以删除该压缩包,执行

并在提示符后输入 y 并回车确认删除。

现在输入

然后按回车键进入该目录。 此时终端提示符应该显示如下。

如果操作无误,执行

并看到一个名为 credit.c 的文件。 执行 code credit.c 应该会打开该文件,你将在其中输入此问题集的代码。 如果没有,请回顾你的步骤,看看你哪里出错了!

信用卡

信用卡(或借记卡)是一种用于支付商品和服务的塑料卡片。 卡上印有的号码会存储在数据库中,以便在消费时,商家可以向你收费。 由于信用卡用户众多,卡号通常很长。 例如,美国运通理论上可以发行多达 10^15 = 1,000,000,000,000,000 张不同的卡!(也就是一千万亿。)

但实际上,信用卡号并非完全随机,而是有一定的结构。 例如,美国运通卡号以 34 或 37 开头,万事达卡号大多以 51、52、53、54 或 55 开头(还有其他开头数字,但我们在此不做讨论),而 Visa 卡号则以 4 开头。信用卡号中还包含一个“校验和”,它是一种基于卡号数字间数学关系的验证码。 校验和可以帮助计算机(或擅长数学的人)检测卡号中的错误(例如数字错位),甚至在不查询数据库的情况下识别欺诈性卡号,从而避免数据库查询的延迟。 当然,高明的造假者也可能生成符合校验和规则的假卡号,因此更严格的验证仍然需要查询数据库。

Luhn 算法

那么这个秘密算法是什么呢? 根据 Luhn 算法,你可以通过以下步骤验证信用卡号的有效性(从语法层面):

  1. 从卡号的倒数第二位开始,将每隔一位的数字乘以 2,然后将所有乘积的各位数字相加。
  2. 将上述结果与卡号中未被乘 2 的数字之和相加。
  3. 如果最终结果的个位数为 0(或者说,结果模 10 等于 0),则该卡号有效!

这可能有点复杂,我们用 David 的 Visa 卡号 4003600000000014 举例说明。

  1. 为了方便演示,我们首先从卡号的倒数第二位开始,在每隔一位的数字下面划线:

    4003600000000014

    接下来,我们将每个带下划线的数字乘以 2:

    1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2

    这给了我们:

    2 + 0 + 0 + 0 + 0 + 12 + 0 + 8

    现在,我们将这些乘积的各位数字相加(注意不是直接相加乘积本身):

    2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13

  2. 现在,我们将 13 与卡号中未被乘以 2 的数字之和相加(从末尾开始):

    13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20

  3. 是的,最终结果 20 的个位数为 0,所以 David 的卡号是有效的!

可见,验证信用卡号并不复杂,但手动计算比较繁琐。 让我们用程序来实现这个算法。

具体实现

credit 目录下的 credit.c 文件中,编写一个程序,提示用户输入信用卡号码,然后根据此处定义的每种格式,通过 printf 报告它是否是有效的 American Express、MasterCard 或 Visa 卡号。为了方便我们自动化测试您的代码,请确保您的程序最后一行输出为 AMEX\nMASTERCARD\nVISA\nINVALID\n,且不多不少。为了简化问题,您可以假设用户输入的是纯数字(不包含连字符,如同信用卡上印刷的数字),且不包含前导零。但请注意,不要假设用户的输入能放入 int 类型中! 建议使用 CS50 库中的 get_long 函数来获取用户输入。(原因请自行思考)

请参考以下示例,了解您的程序在接收到有效的信用卡号码(不含连字符)时应如何运行。

$ ./credit
Number: 4003600000000014
VISA

实际上,get_long 函数本身就会拒绝连字符(以及其他非数字字符):

$ ./credit
Number: 4003-6000-0000-0014
Number: foo
Number: 4003600000000014
VISA

但是,即使输入是纯数字,您也需要负责识别出那些 不是 信用卡号码的输入(例如电话号码)。

$ ./credit
Number: 6176292929
INVALID

请使用大量有效和无效的输入来充分测试您的程序(我们也会这样做!)。以下是 PayPal 推荐用于测试的一些卡号

如果您的程序在某些输入下表现不正确(甚至无法编译),那就需要进行调试了!

步骤详解

如何测试代码

您还可以执行以下命令,使用 check50 评估代码的正确性。 但请务必自己编译并测试它!

check50 cs50/problems/2023/x/credit

执行以下命令,使用 style50 评估代码的风格。

如何提交

在您的终端中,执行以下命令来提交您的工作。

submit50 cs50/problems/2023/x/credit